/* do not edit automatically generated by mc from DynamicStrings.  */
/* DynamicStrings.mod provides a dynamic string type and procedures.

Copyright (C) 2001-2023 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.

This file is part of GNU Modula-2.

GNU Modula-2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GNU Modula-2 is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.

You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
<http://www.gnu.org/licenses/>.  */

#   if !defined (PROC_D)
#      define PROC_D
       typedef void (*PROC_t) (void);
       typedef struct { PROC_t proc; } PROC;
#   endif

#   if !defined (TRUE)
#      define TRUE (1==1)
#   endif

#   if !defined (FALSE)
#      define FALSE (1==0)
#   endif

#include <stddef.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#   include "GStorage.h"
#include <unistd.h>
#if defined(__cplusplus)
#   undef NULL
#   define NULL 0
#endif
#define _DynamicStrings_H
#define _DynamicStrings_C

#   include "Glibc.h"
#   include "GStrLib.h"
#   include "GStorage.h"
#   include "GAssertion.h"
#   include "GSYSTEM.h"
#   include "GASCII.h"
#   include "GM2RTS.h"

#   define MaxBuf 127
#   define PoisonOn FALSE
#   define DebugOn FALSE
#   define CheckOn FALSE
#   define TraceOn FALSE
typedef struct DynamicStrings_Contents_r DynamicStrings_Contents;

typedef struct DynamicStrings_DebugInfo_r DynamicStrings_DebugInfo;

typedef struct DynamicStrings_stringRecord_r DynamicStrings_stringRecord;

typedef struct DynamicStrings_descriptor_r DynamicStrings_descriptor;

typedef DynamicStrings_descriptor *DynamicStrings_Descriptor;

typedef struct DynamicStrings_frameRec_r DynamicStrings_frameRec;

typedef DynamicStrings_frameRec *DynamicStrings_frame;

typedef struct DynamicStrings__T3_a DynamicStrings__T3;

typedef enum {DynamicStrings_inuse, DynamicStrings_marked, DynamicStrings_onlist, DynamicStrings_poisoned} DynamicStrings_desState;

typedef DynamicStrings_stringRecord *DynamicStrings_String;

struct DynamicStrings_DebugInfo_r {
                                    DynamicStrings_String next;
                                    void *file;
                                    unsigned int line;
                                    void *proc;
                                  };

struct DynamicStrings_descriptor_r {
                                     unsigned int charStarUsed;
                                     void *charStar;
                                     unsigned int charStarSize;
                                     unsigned int charStarValid;
                                     DynamicStrings_desState state;
                                     DynamicStrings_String garbage;
                                   };

struct DynamicStrings_frameRec_r {
                                   DynamicStrings_String alloc;
                                   DynamicStrings_String dealloc;
                                   DynamicStrings_frame next;
                                 };

struct DynamicStrings__T3_a { char array[(MaxBuf-1)+1]; };
struct DynamicStrings_Contents_r {
                                   DynamicStrings__T3 buf;
                                   unsigned int len;
                                   DynamicStrings_String next;
                                 };

struct DynamicStrings_stringRecord_r {
                                       DynamicStrings_Contents contents;
                                       DynamicStrings_Descriptor head;
                                       DynamicStrings_DebugInfo debug;
                                     };

static unsigned int Initialized;
static DynamicStrings_frame frameHead;
static DynamicStrings_String captured;

/*
   InitString - creates and returns a String type object.
                Initial contents are, a.
*/

extern "C" DynamicStrings_String DynamicStrings_InitString (const char *a_, unsigned int _a_high);

/*
   KillString - frees String, s, and its contents.
                NIL is returned.
*/

extern "C" DynamicStrings_String DynamicStrings_KillString (DynamicStrings_String s);

/*
   Fin - finishes with a string, it calls KillString with, s.
         The purpose of the procedure is to provide a short cut
         to calling KillString and then testing the return result.
*/

extern "C" void DynamicStrings_Fin (DynamicStrings_String s);

/*
   InitStringCharStar - initializes and returns a String to contain the C string.
*/

extern "C" DynamicStrings_String DynamicStrings_InitStringCharStar (void * a);

/*
   InitStringChar - initializes and returns a String to contain the single character, ch.
*/

extern "C" DynamicStrings_String DynamicStrings_InitStringChar (char ch);

/*
   Mark - marks String, s, ready for garbage collection.
*/

extern "C" DynamicStrings_String DynamicStrings_Mark (DynamicStrings_String s);

/*
   Length - returns the length of the String, s.
*/

extern "C" unsigned int DynamicStrings_Length (DynamicStrings_String s);

/*
   ConCat - returns String, a, after the contents of, b, have been appended.
*/

extern "C" DynamicStrings_String DynamicStrings_ConCat (DynamicStrings_String a, DynamicStrings_String b);

/*
   ConCatChar - returns String, a, after character, ch, has been appended.
*/

extern "C" DynamicStrings_String DynamicStrings_ConCatChar (DynamicStrings_String a, char ch);

/*
   Assign - assigns the contents of, b, into, a.
            String, a, is returned.
*/

extern "C" DynamicStrings_String DynamicStrings_Assign (DynamicStrings_String a, DynamicStrings_String b);

/*
   Dup - duplicate a String, s, returning the copy of s.
*/

extern "C" DynamicStrings_String DynamicStrings_Dup (DynamicStrings_String s);

/*
   Add - returns a new String which contains the contents of a and b.
*/

extern "C" DynamicStrings_String DynamicStrings_Add (DynamicStrings_String a, DynamicStrings_String b);

/*
   Equal - returns TRUE if String, a, and, b, are equal.
*/

extern "C" unsigned int DynamicStrings_Equal (DynamicStrings_String a, DynamicStrings_String b);

/*
   EqualCharStar - returns TRUE if contents of String, s, is the same as the
                   string, a.
*/

extern "C" unsigned int DynamicStrings_EqualCharStar (DynamicStrings_String s, void * a);

/*
   EqualArray - returns TRUE if contents of String, s, is the same as the
                string, a.
*/

extern "C" unsigned int DynamicStrings_EqualArray (DynamicStrings_String s, const char *a_, unsigned int _a_high);

/*
   Mult - returns a new string which is n concatenations of String, s.
*/

extern "C" DynamicStrings_String DynamicStrings_Mult (DynamicStrings_String s, unsigned int n);

/*
   Slice - returns a new string which contains the elements
           low..high-1

           strings start at element 0
           Slice(s, 0, 2)  will return elements 0, 1 but not 2
           Slice(s, 1, 3)  will return elements 1, 2 but not 3
           Slice(s, 2, 0)  will return elements 2..max
           Slice(s, 3, -1) will return elements 3..max-1
           Slice(s, 4, -2) will return elements 4..max-2
*/

extern "C" DynamicStrings_String DynamicStrings_Slice (DynamicStrings_String s, int low, int high);

/*
   Index - returns the indice of the first occurance of, ch, in
           String, s. -1 is returned if, ch, does not exist.
           The search starts at position, o.
*/

extern "C" int DynamicStrings_Index (DynamicStrings_String s, char ch, unsigned int o);

/*
   RIndex - returns the indice of the last occurance of, ch,
            in String, s. The search starts at position, o.
            -1 is returned if, ch, is not found.
*/

extern "C" int DynamicStrings_RIndex (DynamicStrings_String s, char ch, unsigned int o);

/*
   RemoveComment - assuming that, comment, is a comment delimiter
                   which indicates anything to its right is a comment
                   then strip off the comment and also any white space
                   on the remaining right hand side.
                   It leaves any white space on the left hand side alone.
*/

extern "C" DynamicStrings_String DynamicStrings_RemoveComment (DynamicStrings_String s, char comment);

/*
   RemoveWhitePrefix - removes any leading white space from String, s.
                       A new string is returned.
*/

extern "C" DynamicStrings_String DynamicStrings_RemoveWhitePrefix (DynamicStrings_String s);

/*
   RemoveWhitePostfix - removes any leading white space from String, s.
                        A new string is returned.
*/

extern "C" DynamicStrings_String DynamicStrings_RemoveWhitePostfix (DynamicStrings_String s);

/*
   ToUpper - returns string, s, after it has had its lower case characters
             replaced by upper case characters.
             The string, s, is not duplicated.
*/

extern "C" DynamicStrings_String DynamicStrings_ToUpper (DynamicStrings_String s);

/*
   ToLower - returns string, s, after it has had its upper case characters
             replaced by lower case characters.
             The string, s, is not duplicated.
*/

extern "C" DynamicStrings_String DynamicStrings_ToLower (DynamicStrings_String s);

/*
   CopyOut - copies string, s, to a.
*/

extern "C" void DynamicStrings_CopyOut (char *a, unsigned int _a_high, DynamicStrings_String s);

/*
   char - returns the character, ch, at position, i, in String, s.
*/

extern "C" char DynamicStrings_char (DynamicStrings_String s, int i);

/*
   string - returns the C style char * of String, s.
*/

extern "C" void * DynamicStrings_string (DynamicStrings_String s);

/*
   InitStringDB - the debug version of InitString.
*/

extern "C" DynamicStrings_String DynamicStrings_InitStringDB (const char *a_, unsigned int _a_high, const char *file_, unsigned int _file_high, unsigned int line);

/*
   InitStringCharStarDB - the debug version of InitStringCharStar.
*/

extern "C" DynamicStrings_String DynamicStrings_InitStringCharStarDB (void * a, const char *file_, unsigned int _file_high, unsigned int line);

/*
   InitStringCharDB - the debug version of InitStringChar.
*/

extern "C" DynamicStrings_String DynamicStrings_InitStringCharDB (char ch, const char *file_, unsigned int _file_high, unsigned int line);

/*
   MultDB - the debug version of MultDB.
*/

extern "C" DynamicStrings_String DynamicStrings_MultDB (DynamicStrings_String s, unsigned int n, const char *file_, unsigned int _file_high, unsigned int line);

/*
   DupDB - the debug version of Dup.
*/

extern "C" DynamicStrings_String DynamicStrings_DupDB (DynamicStrings_String s, const char *file_, unsigned int _file_high, unsigned int line);

/*
   SliceDB - debug version of Slice.
*/

extern "C" DynamicStrings_String DynamicStrings_SliceDB (DynamicStrings_String s, int low, int high, const char *file_, unsigned int _file_high, unsigned int line);

/*
   PushAllocation - pushes the current allocation/deallocation lists.
*/

extern "C" void DynamicStrings_PushAllocation (void);

/*
   PopAllocation - test to see that all strings are deallocated since
                   the last push.  Then it pops to the previous
                   allocation/deallocation lists.

                   If halt is true then the application terminates
                   with an exit code of 1.
*/

extern "C" void DynamicStrings_PopAllocation (unsigned int halt);

/*
   PopAllocationExemption - test to see that all strings are deallocated, except
                            string, e, since the last push.
                            Then it pops to the previous allocation/deallocation
                            lists.

                            If halt is true then the application terminates
                            with an exit code of 1.
*/

extern "C" DynamicStrings_String DynamicStrings_PopAllocationExemption (unsigned int halt, DynamicStrings_String e);

/*
 writeStringDesc write out debugging information about string, s.  */

static void writeStringDesc (DynamicStrings_String s);

/*
   writeNspace -
*/

static void writeNspace (unsigned int n);

/*
   DumpStringInfo -
*/

static void DumpStringInfo (DynamicStrings_String s, unsigned int i);

/*
   DumpStringInfo -
*/

static void stop (void);

/*
   doDSdbEnter -
*/

static void doDSdbEnter (void);

/*
   doDSdbExit -
*/

static void doDSdbExit (DynamicStrings_String s);

/*
   DSdbEnter -
*/

static void DSdbEnter (void);

/*
   DSdbExit -
*/

static void DSdbExit (DynamicStrings_String s);
static unsigned int Capture (DynamicStrings_String s);

/*
   Min -
*/

static unsigned int Min (unsigned int a, unsigned int b);

/*
   Max -
*/

static unsigned int Max (unsigned int a, unsigned int b);

/*
   writeString - writes a string to stdout.
*/

static void writeString (const char *a_, unsigned int _a_high);

/*
   writeCstring - writes a C string to stdout.
*/

static void writeCstring (void * a);

/*
   writeCard -
*/

static void writeCard (unsigned int c);

/*
   writeLongcard -
*/

static void writeLongcard (long unsigned int l);

/*
   writeAddress -
*/

static void writeAddress (void * a);

/*
   writeLn - writes a newline.
*/

static void writeLn (void);

/*
   AssignDebug - assigns, file, and, line, information to string, s.
*/

static DynamicStrings_String AssignDebug (DynamicStrings_String s, const char *file_, unsigned int _file_high, unsigned int line, const char *proc_, unsigned int _proc_high);

/*
   IsOn - returns TRUE if, s, is on one of the debug lists.
*/

static unsigned int IsOn (DynamicStrings_String list, DynamicStrings_String s);

/*
   AddTo - adds string, s, to, list.
*/

static void AddTo (DynamicStrings_String *list, DynamicStrings_String s);

/*
   SubFrom - removes string, s, from, list.
*/

static void SubFrom (DynamicStrings_String *list, DynamicStrings_String s);

/*
   AddAllocated - adds string, s, to the head of the allocated list.
*/

static void AddAllocated (DynamicStrings_String s);

/*
   AddDeallocated - adds string, s, to the head of the deallocated list.
*/

static void AddDeallocated (DynamicStrings_String s);

/*
   IsOnAllocated - returns TRUE if the string, s, has ever been allocated.
*/

static unsigned int IsOnAllocated (DynamicStrings_String s);

/*
   IsOnDeallocated - returns TRUE if the string, s, has ever been deallocated.
*/

static unsigned int IsOnDeallocated (DynamicStrings_String s);

/*
   SubAllocated - removes string, s, from the list of allocated strings.
*/

static void SubAllocated (DynamicStrings_String s);

/*
   SubDeallocated - removes string, s, from the list of deallocated strings.
*/

static void SubDeallocated (DynamicStrings_String s);

/*
   SubDebugInfo - removes string, s, from the list of allocated strings.
*/

static void SubDebugInfo (DynamicStrings_String s);

/*
   AddDebugInfo - adds string, s, to the list of allocated strings.
*/

static void AddDebugInfo (DynamicStrings_String s);

/*
   ConcatContents - add the contents of string, a, where, h, is the
                    total length of, a. The offset is in, o.
*/

static void ConcatContents (DynamicStrings_Contents *c, const char *a_, unsigned int _a_high, unsigned int h, unsigned int o);

/*
   DeallocateCharStar - deallocates any charStar.
*/

static void DeallocateCharStar (DynamicStrings_String s);

/*
   CheckPoisoned - checks for a poisoned string, s.
*/

static DynamicStrings_String CheckPoisoned (DynamicStrings_String s);

/*
   MarkInvalid - marks the char * version of String, s, as invalid.
*/

static void MarkInvalid (DynamicStrings_String s);

/*
   ConcatContentsAddress - concatenate the string, a, where, h, is the
                           total length of, a.
*/

static void ConcatContentsAddress (DynamicStrings_Contents *c, void * a, unsigned int h);

/*
   AddToGarbage - adds String, b, onto the garbage list of, a.  Providing
                  the state of b is marked.  The state is then altered to
                  onlist.  String, a, is returned.
*/

static DynamicStrings_String AddToGarbage (DynamicStrings_String a, DynamicStrings_String b);

/*
   IsOnGarbage - returns TRUE if, s, is on string, e, garbage list.
*/

static unsigned int IsOnGarbage (DynamicStrings_String e, DynamicStrings_String s);

/*
   IsWhite - returns TRUE if, ch, is a space or a tab.
*/

static unsigned int IsWhite (char ch);

/*
   DumpState -
*/

static void DumpState (DynamicStrings_String s);

/*
   DumpStringSynopsis -
*/

static void DumpStringSynopsis (DynamicStrings_String s);

/*
   DumpString - displays the contents of string, s.
*/

static void DumpString (DynamicStrings_String s);

/*
   Init - initialize the module.
*/

static void Init (void);


/*
 writeStringDesc write out debugging information about string, s.  */

static void writeStringDesc (DynamicStrings_String s)
{
  writeCstring (s->debug.file);
  writeString ((const char *) ":", 1);
  writeCard (s->debug.line);
  writeString ((const char *) ":", 1);
  writeCstring (s->debug.proc);
  writeString ((const char *) " ", 1);
  writeAddress (reinterpret_cast<void *> (s));
  writeString ((const char *) " ", 1);
  switch (s->head->state)
    {
      case DynamicStrings_inuse:
        writeString ((const char *) "still in use (", 14);
        writeCard (s->contents.len);
        writeString ((const char *) ") characters", 12);
        break;

      case DynamicStrings_marked:
        writeString ((const char *) "marked", 6);
        break;

      case DynamicStrings_onlist:
        writeString ((const char *) "on a (lost) garbage list", 24);
        break;

      case DynamicStrings_poisoned:
        writeString ((const char *) "poisoned", 8);
        break;


      default:
        writeString ((const char *) "unknown state", 13);
        break;
    }
}


/*
   writeNspace -
*/

static void writeNspace (unsigned int n)
{
  while (n > 0)
    {
      writeString ((const char *) " ", 1);
      n -= 1;
    }
}


/*
   DumpStringInfo -
*/

static void DumpStringInfo (DynamicStrings_String s, unsigned int i)
{
  DynamicStrings_String t;

  if (s != NULL)
    {
      writeNspace (i);
      writeStringDesc (s);
      writeLn ();
      if (s->head->garbage != NULL)
        {
          writeNspace (i);
          writeString ((const char *) "garbage list:", 13);
          writeLn ();
          do {
            s = s->head->garbage;
            DumpStringInfo (s, i+1);
            writeLn ();
          } while (! (s == NULL));
        }
    }
}


/*
   DumpStringInfo -
*/

static void stop (void)
{
}


/*
   doDSdbEnter -
*/

static void doDSdbEnter (void)
{
  if (CheckOn)
    {
      DynamicStrings_PushAllocation ();
    }
}


/*
   doDSdbExit -
*/

static void doDSdbExit (DynamicStrings_String s)
{
  if (CheckOn)
    {
      s = DynamicStrings_PopAllocationExemption (TRUE, s);
    }
}


/*
   DSdbEnter -
*/

static void DSdbEnter (void)
{
}


/*
   DSdbExit -
*/

static void DSdbExit (DynamicStrings_String s)
{
}

static unsigned int Capture (DynamicStrings_String s)
{
  /* 
 *   #undef GM2_DEBUG_DYNAMICSTINGS
 *   #if defined(GM2_DEBUG_DYNAMICSTINGS)
 *   #  define DSdbEnter doDSdbEnter
 *   #  define DSdbExit  doDSdbExit
 *   #  define CheckOn   TRUE
 *   #  define TraceOn   TRUE
 *   #endif
  */
  captured = s;
  return 1;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Min -
*/

static unsigned int Min (unsigned int a, unsigned int b)
{
  if (a < b)
    {
      return a;
    }
  else
    {
      return b;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Max -
*/

static unsigned int Max (unsigned int a, unsigned int b)
{
  if (a > b)
    {
      return a;
    }
  else
    {
      return b;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   writeString - writes a string to stdout.
*/

static void writeString (const char *a_, unsigned int _a_high)
{
  int i;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  i = static_cast<int> (libc_write (1, &a, static_cast<size_t> (StrLib_StrLen ((const char *) a, _a_high))));
}


/*
   writeCstring - writes a C string to stdout.
*/

static void writeCstring (void * a)
{
  int i;

  if (a == NULL)
    {
      writeString ((const char *) "(null)", 6);
    }
  else
    {
      i = static_cast<int> (libc_write (1, a, libc_strlen (a)));
    }
}


/*
   writeCard -
*/

static void writeCard (unsigned int c)
{
  char ch;
  int i;

  if (c > 9)
    {
      writeCard (c / 10);
      writeCard (c % 10);
    }
  else
    {
      ch = ((char) ( ((unsigned int) ('0'))+c));
      i = static_cast<int> (libc_write (1, &ch, static_cast<size_t> (1)));
    }
}


/*
   writeLongcard -
*/

static void writeLongcard (long unsigned int l)
{
  char ch;
  int i;

  if (l > 16)
    {
      writeLongcard (l / 16);
      writeLongcard (l % 16);
    }
  else if (l < 10)
    {
      /* avoid dangling else.  */
      ch = ((char) ( ((unsigned int) ('0'))+((unsigned int ) (l))));
      i = static_cast<int> (libc_write (1, &ch, static_cast<size_t> (1)));
    }
  else if (l < 16)
    {
      /* avoid dangling else.  */
      ch = ((char) (( ((unsigned int) ('a'))+((unsigned int ) (l)))-10));
      i = static_cast<int> (libc_write (1, &ch, static_cast<size_t> (1)));
    }
}


/*
   writeAddress -
*/

static void writeAddress (void * a)
{
  writeLongcard ((long unsigned int ) (a));
}


/*
   writeLn - writes a newline.
*/

static void writeLn (void)
{
  char ch;
  int i;

  ch = ASCII_lf;
  i = static_cast<int> (libc_write (1, &ch, static_cast<size_t> (1)));
}


/*
   AssignDebug - assigns, file, and, line, information to string, s.
*/

static DynamicStrings_String AssignDebug (DynamicStrings_String s, const char *file_, unsigned int _file_high, unsigned int line, const char *proc_, unsigned int _proc_high)
{
  void * f;
  void * p;
  char file[_file_high+1];
  char proc[_proc_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (file, file_, _file_high+1);
  memcpy (proc, proc_, _proc_high+1);

  f = &file;
  p = &proc;
  Storage_ALLOCATE (&s->debug.file, (StrLib_StrLen ((const char *) file, _file_high))+1);
  if ((libc_strncpy (s->debug.file, f, (StrLib_StrLen ((const char *) file, _file_high))+1)) == NULL)
    {}  /* empty.  */
  s->debug.line = line;
  Storage_ALLOCATE (&s->debug.proc, (StrLib_StrLen ((const char *) proc, _proc_high))+1);
  if ((libc_strncpy (s->debug.proc, p, (StrLib_StrLen ((const char *) proc, _proc_high))+1)) == NULL)
    {}  /* empty.  */
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IsOn - returns TRUE if, s, is on one of the debug lists.
*/

static unsigned int IsOn (DynamicStrings_String list, DynamicStrings_String s)
{
  while ((list != s) && (list != NULL))
    {
      list = list->debug.next;
    }
  return list == s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   AddTo - adds string, s, to, list.
*/

static void AddTo (DynamicStrings_String *list, DynamicStrings_String s)
{
  if ((*list) == NULL)
    {
      (*list) = s;
      s->debug.next = NULL;
    }
  else
    {
      s->debug.next = (*list);
      (*list) = s;
    }
}


/*
   SubFrom - removes string, s, from, list.
*/

static void SubFrom (DynamicStrings_String *list, DynamicStrings_String s)
{
  DynamicStrings_String p;

  if ((*list) == s)
    {
      (*list) = s->debug.next;
    }
  else
    {
      p = (*list);
      while ((p->debug.next != NULL) && (p->debug.next != s))
        {
          p = p->debug.next;
        }
      if (p->debug.next == s)
        {
          p->debug.next = s->debug.next;
        }
      else
        {
          /* not found, quit  */
          return ;
        }
    }
  s->debug.next = NULL;
}


/*
   AddAllocated - adds string, s, to the head of the allocated list.
*/

static void AddAllocated (DynamicStrings_String s)
{
  Init ();
  AddTo (&frameHead->alloc, s);
}


/*
   AddDeallocated - adds string, s, to the head of the deallocated list.
*/

static void AddDeallocated (DynamicStrings_String s)
{
  Init ();
  AddTo (&frameHead->dealloc, s);
}


/*
   IsOnAllocated - returns TRUE if the string, s, has ever been allocated.
*/

static unsigned int IsOnAllocated (DynamicStrings_String s)
{
  DynamicStrings_frame f;

  Init ();
  f = frameHead;
  do {
    if (IsOn (f->alloc, s))
      {
        return TRUE;
      }
    else
      {
        f = f->next;
      }
  } while (! (f == NULL));
  return FALSE;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IsOnDeallocated - returns TRUE if the string, s, has ever been deallocated.
*/

static unsigned int IsOnDeallocated (DynamicStrings_String s)
{
  DynamicStrings_frame f;

  Init ();
  f = frameHead;
  do {
    if (IsOn (f->dealloc, s))
      {
        return TRUE;
      }
    else
      {
        f = f->next;
      }
  } while (! (f == NULL));
  return FALSE;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   SubAllocated - removes string, s, from the list of allocated strings.
*/

static void SubAllocated (DynamicStrings_String s)
{
  DynamicStrings_frame f;

  Init ();
  f = frameHead;
  do {
    if (IsOn (f->alloc, s))
      {
        SubFrom (&f->alloc, s);
        return ;
      }
    else
      {
        f = f->next;
      }
  } while (! (f == NULL));
}


/*
   SubDeallocated - removes string, s, from the list of deallocated strings.
*/

static void SubDeallocated (DynamicStrings_String s)
{
  DynamicStrings_frame f;

  Init ();
  f = frameHead;
  do {
    if (IsOn (f->dealloc, s))
      {
        SubFrom (&f->dealloc, s);
        return ;
      }
    else
      {
        f = f->next;
      }
  } while (! (f == NULL));
}


/*
   SubDebugInfo - removes string, s, from the list of allocated strings.
*/

static void SubDebugInfo (DynamicStrings_String s)
{
  if (IsOnDeallocated (s))
    {
      Assertion_Assert (! DebugOn);
      /* string has already been deallocated  */
      return ;
    }
  if (IsOnAllocated (s))
    {
      SubAllocated (s);
      AddDeallocated (s);
    }
  else
    {
      /* string has not been allocated  */
      Assertion_Assert (! DebugOn);
    }
}


/*
   AddDebugInfo - adds string, s, to the list of allocated strings.
*/

static void AddDebugInfo (DynamicStrings_String s)
{
  s->debug.next = NULL;
  s->debug.file = NULL;
  s->debug.line = 0;
  s->debug.proc = NULL;
  if (CheckOn)
    {
      AddAllocated (s);
    }
}


/*
   ConcatContents - add the contents of string, a, where, h, is the
                    total length of, a. The offset is in, o.
*/

static void ConcatContents (DynamicStrings_Contents *c, const char *a_, unsigned int _a_high, unsigned int h, unsigned int o)
{
  unsigned int i;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  i = (*c).len;
  while ((o < h) && (i < MaxBuf))
    {
      (*c).buf.array[i] = a[o];
      o += 1;
      i += 1;
    }
  if (o < h)
    {
      (*c).len = MaxBuf;
      Storage_ALLOCATE ((void **) &(*c).next, sizeof (DynamicStrings_stringRecord));
      (*c).next->head = NULL;
      (*c).next->contents.len = 0;
      (*c).next->contents.next = NULL;
      ConcatContents (&(*c).next->contents, (const char *) a, _a_high, h, o);
      AddDebugInfo ((*c).next);
      (*c).next = AssignDebug ((*c).next, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 722, (const char *) "ConcatContents", 14);
    }
  else
    {
      (*c).len = i;
    }
}


/*
   DeallocateCharStar - deallocates any charStar.
*/

static void DeallocateCharStar (DynamicStrings_String s)
{
  if ((s != NULL) && (s->head != NULL))
    {
      if (s->head->charStarUsed && (s->head->charStar != NULL))
        {
          Storage_DEALLOCATE (&s->head->charStar, s->head->charStarSize);
        }
      s->head->charStarUsed = FALSE;
      s->head->charStar = NULL;
      s->head->charStarSize = 0;
      s->head->charStarValid = FALSE;
    }
}


/*
   CheckPoisoned - checks for a poisoned string, s.
*/

static DynamicStrings_String CheckPoisoned (DynamicStrings_String s)
{
  if (((PoisonOn && (s != NULL)) && (s->head != NULL)) && (s->head->state == DynamicStrings_poisoned))
    {
      M2RTS_HALT (-1);
      __builtin_unreachable ();
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   MarkInvalid - marks the char * version of String, s, as invalid.
*/

static void MarkInvalid (DynamicStrings_String s)
{
  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  if (s->head != NULL)
    {
      s->head->charStarValid = FALSE;
    }
}


/*
   ConcatContentsAddress - concatenate the string, a, where, h, is the
                           total length of, a.
*/

static void ConcatContentsAddress (DynamicStrings_Contents *c, void * a, unsigned int h)
{
  typedef char *ConcatContentsAddress__T1;

  ConcatContentsAddress__T1 p;
  unsigned int i;
  unsigned int j;

  j = 0;
  i = (*c).len;
  p = static_cast<ConcatContentsAddress__T1> (a);
  while ((j < h) && (i < MaxBuf))
    {
      (*c).buf.array[i] = (*p);
      i += 1;
      j += 1;
      p += 1;
    }
  if (j < h)
    {
      /* avoid dangling else.  */
      (*c).len = MaxBuf;
      Storage_ALLOCATE ((void **) &(*c).next, sizeof (DynamicStrings_stringRecord));
      (*c).next->head = NULL;
      (*c).next->contents.len = 0;
      (*c).next->contents.next = NULL;
      ConcatContentsAddress (&(*c).next->contents, reinterpret_cast<void *> (p), h-j);
      AddDebugInfo ((*c).next);
      if (TraceOn)
        {
          (*c).next = AssignDebug ((*c).next, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 917, (const char *) "ConcatContentsAddress", 21);
        }
    }
  else
    {
      (*c).len = i;
      (*c).next = NULL;
    }
}


/*
   AddToGarbage - adds String, b, onto the garbage list of, a.  Providing
                  the state of b is marked.  The state is then altered to
                  onlist.  String, a, is returned.
*/

static DynamicStrings_String AddToGarbage (DynamicStrings_String a, DynamicStrings_String b)
{
  DynamicStrings_String c;

  if (PoisonOn)
    {
      a = CheckPoisoned (a);
      b = CheckPoisoned (b);
    }
  /* 
   IF (a#NIL) AND (a#b) AND (a^.head^.state=marked)
   THEN
      writeString('warning trying to add to a marked string') ; writeLn
   END ;
  */
  if (((((a != b) && (a != NULL)) && (b != NULL)) && (b->head->state == DynamicStrings_marked)) && (a->head->state == DynamicStrings_inuse))
    {
      c = a;
      while (c->head->garbage != NULL)
        {
          c = c->head->garbage;
        }
      c->head->garbage = b;
      b->head->state = DynamicStrings_onlist;
      if (CheckOn)
        {
          SubDebugInfo (b);
        }
    }
  return a;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IsOnGarbage - returns TRUE if, s, is on string, e, garbage list.
*/

static unsigned int IsOnGarbage (DynamicStrings_String e, DynamicStrings_String s)
{
  if ((e != NULL) && (s != NULL))
    {
      while (e->head->garbage != NULL)
        {
          if (e->head->garbage == s)
            {
              return TRUE;
            }
          else
            {
              e = e->head->garbage;
            }
        }
    }
  return FALSE;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   IsWhite - returns TRUE if, ch, is a space or a tab.
*/

static unsigned int IsWhite (char ch)
{
  return (ch == ' ') || (ch == ASCII_tab);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   DumpState -
*/

static void DumpState (DynamicStrings_String s)
{
  switch (s->head->state)
    {
      case DynamicStrings_inuse:
        writeString ((const char *) "still in use (", 14);
        writeCard (s->contents.len);
        writeString ((const char *) ") characters", 12);
        break;

      case DynamicStrings_marked:
        writeString ((const char *) "marked", 6);
        break;

      case DynamicStrings_onlist:
        writeString ((const char *) "on a garbage list", 17);
        break;

      case DynamicStrings_poisoned:
        writeString ((const char *) "poisoned", 8);
        break;


      default:
        writeString ((const char *) "unknown state", 13);
        break;
    }
}


/*
   DumpStringSynopsis -
*/

static void DumpStringSynopsis (DynamicStrings_String s)
{
  writeCstring (s->debug.file);
  writeString ((const char *) ":", 1);
  writeCard (s->debug.line);
  writeString ((const char *) ":", 1);
  writeCstring (s->debug.proc);
  writeString ((const char *) " string ", 8);
  writeAddress (reinterpret_cast<void *> (s));
  writeString ((const char *) " ", 1);
  DumpState (s);
  if (IsOnAllocated (s))
    {
      writeString ((const char *) " globally allocated", 19);
    }
  else if (IsOnDeallocated (s))
    {
      /* avoid dangling else.  */
      writeString ((const char *) " globally deallocated", 21);
    }
  else
    {
      /* avoid dangling else.  */
      writeString ((const char *) " globally unknown", 17);
    }
  writeLn ();
}


/*
   DumpString - displays the contents of string, s.
*/

static void DumpString (DynamicStrings_String s)
{
  DynamicStrings_String t;

  if (s != NULL)
    {
      DumpStringSynopsis (s);
      if ((s->head != NULL) && (s->head->garbage != NULL))
        {
          writeString ((const char *) "display chained strings on the garbage list", 43);
          writeLn ();
          t = s->head->garbage;
          while (t != NULL)
            {
              DumpStringSynopsis (t);
              t = t->head->garbage;
            }
        }
    }
}


/*
   Init - initialize the module.
*/

static void Init (void)
{
  if (! Initialized)
    {
      Initialized = TRUE;
      frameHead = NULL;
      DynamicStrings_PushAllocation ();
    }
}


/*
   InitString - creates and returns a String type object.
                Initial contents are, a.
*/

extern "C" DynamicStrings_String DynamicStrings_InitString (const char *a_, unsigned int _a_high)
{
  DynamicStrings_String s;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  Storage_ALLOCATE ((void **) &s, sizeof (DynamicStrings_stringRecord));
  s->contents.len = 0;
  s->contents.next = NULL;
  ConcatContents (&s->contents, (const char *) a, _a_high, StrLib_StrLen ((const char *) a, _a_high), 0);
  Storage_ALLOCATE ((void **) &s->head, sizeof (DynamicStrings_descriptor));
  s->head->charStarUsed = FALSE;
  s->head->charStar = NULL;
  s->head->charStarSize = 0;
  s->head->charStarValid = FALSE;
  s->head->garbage = NULL;
  s->head->state = DynamicStrings_inuse;
  AddDebugInfo (s);
  if (TraceOn)
    {
      s = AssignDebug (s, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 758, (const char *) "InitString", 10);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   KillString - frees String, s, and its contents.
                NIL is returned.
*/

extern "C" DynamicStrings_String DynamicStrings_KillString (DynamicStrings_String s)
{
  DynamicStrings_String t;

  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  if (s != NULL)
    {
      if (CheckOn)
        {
          /* avoid gcc warning by using compound statement even if not strictly necessary.  */
          if (IsOnAllocated (s))
            {
              SubAllocated (s);
            }
          else if (IsOnDeallocated (s))
            {
              /* avoid dangling else.  */
              SubDeallocated (s);
            }
        }
      if (s->head != NULL)
        {
          s->head->state = DynamicStrings_poisoned;
          s->head->garbage = DynamicStrings_KillString (s->head->garbage);
          if (! PoisonOn)
            {
              DeallocateCharStar (s);
            }
          if (! PoisonOn)
            {
              Storage_DEALLOCATE ((void **) &s->head, sizeof (DynamicStrings_descriptor));
              s->head = NULL;
            }
        }
      t = DynamicStrings_KillString (s->contents.next);
      if (! PoisonOn)
        {
          Storage_DEALLOCATE ((void **) &s, sizeof (DynamicStrings_stringRecord));
        }
    }
  return NULL;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Fin - finishes with a string, it calls KillString with, s.
         The purpose of the procedure is to provide a short cut
         to calling KillString and then testing the return result.
*/

extern "C" void DynamicStrings_Fin (DynamicStrings_String s)
{
  if ((DynamicStrings_KillString (s)) != NULL)
    {
      M2RTS_HALT (-1);
      __builtin_unreachable ();
    }
}


/*
   InitStringCharStar - initializes and returns a String to contain the C string.
*/

extern "C" DynamicStrings_String DynamicStrings_InitStringCharStar (void * a)
{
  DynamicStrings_String s;

  Storage_ALLOCATE ((void **) &s, sizeof (DynamicStrings_stringRecord));
  s->contents.len = 0;
  s->contents.next = NULL;
  if (a != NULL)
    {
      ConcatContentsAddress (&s->contents, a, static_cast<unsigned int> (libc_strlen (a)));
    }
  Storage_ALLOCATE ((void **) &s->head, sizeof (DynamicStrings_descriptor));
  s->head->charStarUsed = FALSE;
  s->head->charStar = NULL;
  s->head->charStarSize = 0;
  s->head->charStarValid = FALSE;
  s->head->garbage = NULL;
  s->head->state = DynamicStrings_inuse;
  AddDebugInfo (s);
  if (TraceOn)
    {
      s = AssignDebug (s, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 957, (const char *) "InitStringCharStar", 18);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   InitStringChar - initializes and returns a String to contain the single character, ch.
*/

extern "C" DynamicStrings_String DynamicStrings_InitStringChar (char ch)
{
  typedef struct InitStringChar__T4_a InitStringChar__T4;

  struct InitStringChar__T4_a { char array[1+1]; };
  InitStringChar__T4 a;
  DynamicStrings_String s;

  a.array[0] = ch;
  a.array[1] = ASCII_nul;
  s = DynamicStrings_InitString ((const char *) &a.array[0], 1);
  if (TraceOn)
    {
      s = AssignDebug (s, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 977, (const char *) "InitStringChar", 14);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Mark - marks String, s, ready for garbage collection.
*/

extern "C" DynamicStrings_String DynamicStrings_Mark (DynamicStrings_String s)
{
  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  if ((s != NULL) && (s->head->state == DynamicStrings_inuse))
    {
      s->head->state = DynamicStrings_marked;
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Length - returns the length of the String, s.
*/

extern "C" unsigned int DynamicStrings_Length (DynamicStrings_String s)
{
  if (s == NULL)
    {
      return 0;
    }
  else
    {
      return s->contents.len+(DynamicStrings_Length (s->contents.next));
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   ConCat - returns String, a, after the contents of, b, have been appended.
*/

extern "C" DynamicStrings_String DynamicStrings_ConCat (DynamicStrings_String a, DynamicStrings_String b)
{
  DynamicStrings_String t;

  if (PoisonOn)
    {
      a = CheckPoisoned (a);
      b = CheckPoisoned (b);
    }
  if (a == b)
    {
      return DynamicStrings_ConCat (a, DynamicStrings_Mark (DynamicStrings_Dup (b)));
    }
  else if (a != NULL)
    {
      /* avoid dangling else.  */
      a = AddToGarbage (a, b);
      MarkInvalid (a);
      t = a;
      while (b != NULL)
        {
          while ((t->contents.len == MaxBuf) && (t->contents.next != NULL))
            {
              t = t->contents.next;
            }
          ConcatContents (&t->contents, (const char *) &b->contents.buf.array[0], (MaxBuf-1), b->contents.len, 0);
          b = b->contents.next;
        }
    }
  if ((a == NULL) && (b != NULL))
    {
      M2RTS_HALT (-1);
      __builtin_unreachable ();
    }
  return a;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   ConCatChar - returns String, a, after character, ch, has been appended.
*/

extern "C" DynamicStrings_String DynamicStrings_ConCatChar (DynamicStrings_String a, char ch)
{
  typedef struct ConCatChar__T5_a ConCatChar__T5;

  struct ConCatChar__T5_a { char array[1+1]; };
  ConCatChar__T5 b;
  DynamicStrings_String t;

  if (PoisonOn)
    {
      a = CheckPoisoned (a);
    }
  b.array[0] = ch;
  b.array[1] = ASCII_nul;
  t = a;
  MarkInvalid (a);
  while ((t->contents.len == MaxBuf) && (t->contents.next != NULL))
    {
      t = t->contents.next;
    }
  ConcatContents (&t->contents, (const char *) &b.array[0], 1, 1, 0);
  return a;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Assign - assigns the contents of, b, into, a.
            String, a, is returned.
*/

extern "C" DynamicStrings_String DynamicStrings_Assign (DynamicStrings_String a, DynamicStrings_String b)
{
  if (PoisonOn)
    {
      a = CheckPoisoned (a);
      b = CheckPoisoned (b);
    }
  if ((a != NULL) && (b != NULL))
    {
      a->contents.next = DynamicStrings_KillString (a->contents.next);
      a->contents.len = 0;
    }
  return DynamicStrings_ConCat (a, b);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Dup - duplicate a String, s, returning the copy of s.
*/

extern "C" DynamicStrings_String DynamicStrings_Dup (DynamicStrings_String s)
{
  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  s = DynamicStrings_Assign (DynamicStrings_InitString ((const char *) "", 0), s);
  if (TraceOn)
    {
      s = AssignDebug (s, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 1173, (const char *) "Dup", 3);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Add - returns a new String which contains the contents of a and b.
*/

extern "C" DynamicStrings_String DynamicStrings_Add (DynamicStrings_String a, DynamicStrings_String b)
{
  if (PoisonOn)
    {
      a = CheckPoisoned (a);
      b = CheckPoisoned (b);
    }
  a = DynamicStrings_ConCat (DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "", 0), a), b);
  if (TraceOn)
    {
      a = AssignDebug (a, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 1193, (const char *) "Add", 3);
    }
  return a;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Equal - returns TRUE if String, a, and, b, are equal.
*/

extern "C" unsigned int DynamicStrings_Equal (DynamicStrings_String a, DynamicStrings_String b)
{
  unsigned int i;

  if (PoisonOn)
    {
      a = CheckPoisoned (a);
      b = CheckPoisoned (b);
    }
  if ((DynamicStrings_Length (a)) == (DynamicStrings_Length (b)))
    {
      while ((a != NULL) && (b != NULL))
        {
          i = 0;
          Assertion_Assert (a->contents.len == b->contents.len);
          while (i < a->contents.len)
            {
              if (a->contents.buf.array[i] != b->contents.buf.array[i])
                {
                  return FALSE;
                }
              i += 1;
            }
          a = a->contents.next;
          b = b->contents.next;
        }
      return TRUE;
    }
  else
    {
      return FALSE;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   EqualCharStar - returns TRUE if contents of String, s, is the same as the
                   string, a.
*/

extern "C" unsigned int DynamicStrings_EqualCharStar (DynamicStrings_String s, void * a)
{
  DynamicStrings_String t;

  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  t = DynamicStrings_InitStringCharStar (a);
  if (TraceOn)
    {
      t = AssignDebug (t, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 1250, (const char *) "EqualCharStar", 13);
    }
  t = AddToGarbage (t, s);
  if (DynamicStrings_Equal (t, s))
    {
      t = DynamicStrings_KillString (t);
      return TRUE;
    }
  else
    {
      t = DynamicStrings_KillString (t);
      return FALSE;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   EqualArray - returns TRUE if contents of String, s, is the same as the
                string, a.
*/

extern "C" unsigned int DynamicStrings_EqualArray (DynamicStrings_String s, const char *a_, unsigned int _a_high)
{
  DynamicStrings_String t;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  t = DynamicStrings_InitString ((const char *) a, _a_high);
  if (TraceOn)
    {
      t = AssignDebug (t, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 1280, (const char *) "EqualArray", 10);
    }
  t = AddToGarbage (t, s);
  if (DynamicStrings_Equal (t, s))
    {
      t = DynamicStrings_KillString (t);
      return TRUE;
    }
  else
    {
      t = DynamicStrings_KillString (t);
      return FALSE;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Mult - returns a new string which is n concatenations of String, s.
*/

extern "C" DynamicStrings_String DynamicStrings_Mult (DynamicStrings_String s, unsigned int n)
{
  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  if (n <= 0)
    {
      s = AddToGarbage (DynamicStrings_InitString ((const char *) "", 0), s);
    }
  else
    {
      s = DynamicStrings_ConCat (DynamicStrings_Mult (s, n-1), s);
    }
  if (TraceOn)
    {
      s = AssignDebug (s, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 1312, (const char *) "Mult", 4);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Slice - returns a new string which contains the elements
           low..high-1

           strings start at element 0
           Slice(s, 0, 2)  will return elements 0, 1 but not 2
           Slice(s, 1, 3)  will return elements 1, 2 but not 3
           Slice(s, 2, 0)  will return elements 2..max
           Slice(s, 3, -1) will return elements 3..max-1
           Slice(s, 4, -2) will return elements 4..max-2
*/

extern "C" DynamicStrings_String DynamicStrings_Slice (DynamicStrings_String s, int low, int high)
{
  DynamicStrings_String d;
  DynamicStrings_String t;
  int start;
  int end;
  int o;

  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  if (low < 0)
    {
      low = ((int ) (DynamicStrings_Length (s)))+low;
    }
  if (high <= 0)
    {
      high = ((int ) (DynamicStrings_Length (s)))+high;
    }
  else
    {
      /* make sure high is <= Length (s)  */
      high = Min (DynamicStrings_Length (s), static_cast<unsigned int> (high));
    }
  d = DynamicStrings_InitString ((const char *) "", 0);
  d = AddToGarbage (d, s);
  o = 0;
  t = d;
  while (s != NULL)
    {
      if (low < (o+((int ) (s->contents.len))))
        {
          if (o > high)
            {
              s = NULL;
            }
          else
            {
              /* found sliceable unit  */
              if (low < o)
                {
                  start = 0;
                }
              else
                {
                  start = low-o;
                }
              end = Max (Min (MaxBuf, static_cast<unsigned int> (high-o)), 0);
              while (t->contents.len == MaxBuf)
                {
                  if (t->contents.next == NULL)
                    {
                      Storage_ALLOCATE ((void **) &t->contents.next, sizeof (DynamicStrings_stringRecord));
                      t->contents.next->head = NULL;
                      t->contents.next->contents.len = 0;
                      AddDebugInfo (t->contents.next);
                      if (TraceOn)
                        {
                          t->contents.next = AssignDebug (t->contents.next, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 1380, (const char *) "Slice", 5);
                        }
                    }
                  t = t->contents.next;
                }
              ConcatContentsAddress (&t->contents, &s->contents.buf.array[start], static_cast<unsigned int> (end-start));
              o += s->contents.len;
              s = s->contents.next;
            }
        }
      else
        {
          o += s->contents.len;
          s = s->contents.next;
        }
    }
  if (TraceOn)
    {
      d = AssignDebug (d, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 1397, (const char *) "Slice", 5);
    }
  return d;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   Index - returns the indice of the first occurance of, ch, in
           String, s. -1 is returned if, ch, does not exist.
           The search starts at position, o.
*/

extern "C" int DynamicStrings_Index (DynamicStrings_String s, char ch, unsigned int o)
{
  unsigned int i;
  unsigned int k;

  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  k = 0;
  while (s != NULL)
    {
      if ((k+s->contents.len) < o)
        {
          k += s->contents.len;
        }
      else
        {
          i = o-k;
          while (i < s->contents.len)
            {
              if (s->contents.buf.array[i] == ch)
                {
                  return k+i;
                }
              i += 1;
            }
          k += i;
          o = k;
        }
      s = s->contents.next;
    }
  return -1;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   RIndex - returns the indice of the last occurance of, ch,
            in String, s. The search starts at position, o.
            -1 is returned if, ch, is not found.
*/

extern "C" int DynamicStrings_RIndex (DynamicStrings_String s, char ch, unsigned int o)
{
  unsigned int i;
  unsigned int k;
  int j;

  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  j = -1;
  k = 0;
  while (s != NULL)
    {
      if ((k+s->contents.len) < o)
        {
          k += s->contents.len;
        }
      else
        {
          if (o < k)
            {
              i = 0;
            }
          else
            {
              i = o-k;
            }
          while (i < s->contents.len)
            {
              if (s->contents.buf.array[i] == ch)
                {
                  j = k;
                }
              k += 1;
              i += 1;
            }
        }
      s = s->contents.next;
    }
  return j;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   RemoveComment - assuming that, comment, is a comment delimiter
                   which indicates anything to its right is a comment
                   then strip off the comment and also any white space
                   on the remaining right hand side.
                   It leaves any white space on the left hand side alone.
*/

extern "C" DynamicStrings_String DynamicStrings_RemoveComment (DynamicStrings_String s, char comment)
{
  int i;

  i = DynamicStrings_Index (s, comment, 0);
  if (i == 0)
    {
      s = DynamicStrings_InitString ((const char *) "", 0);
    }
  else if (i > 0)
    {
      /* avoid dangling else.  */
      s = DynamicStrings_RemoveWhitePostfix (DynamicStrings_Slice (DynamicStrings_Mark (s), 0, i));
    }
  if (TraceOn)
    {
      s = AssignDebug (s, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 1509, (const char *) "RemoveComment", 13);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   RemoveWhitePrefix - removes any leading white space from String, s.
                       A new string is returned.
*/

extern "C" DynamicStrings_String DynamicStrings_RemoveWhitePrefix (DynamicStrings_String s)
{
  unsigned int i;

  i = 0;
  while (IsWhite (DynamicStrings_char (s, static_cast<int> (i))))
    {
      i += 1;
    }
  s = DynamicStrings_Slice (s, (int ) (i), 0);
  if (TraceOn)
    {
      s = AssignDebug (s, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 1621, (const char *) "RemoveWhitePrefix", 17);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   RemoveWhitePostfix - removes any leading white space from String, s.
                        A new string is returned.
*/

extern "C" DynamicStrings_String DynamicStrings_RemoveWhitePostfix (DynamicStrings_String s)
{
  int i;

  i = ((int ) (DynamicStrings_Length (s)))-1;
  while ((i >= 0) && (IsWhite (DynamicStrings_char (s, i))))
    {
      i -= 1;
    }
  s = DynamicStrings_Slice (s, 0, i+1);
  if (TraceOn)
    {
      s = AssignDebug (s, (const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 1643, (const char *) "RemoveWhitePostfix", 18);
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   ToUpper - returns string, s, after it has had its lower case characters
             replaced by upper case characters.
             The string, s, is not duplicated.
*/

extern "C" DynamicStrings_String DynamicStrings_ToUpper (DynamicStrings_String s)
{
  char ch;
  unsigned int i;
  DynamicStrings_String t;

  if (s != NULL)
    {
      MarkInvalid (s);
      t = s;
      while (t != NULL)
        {
          i = 0;
          while (i < t->contents.len)
            {
              ch = t->contents.buf.array[i];
              if ((ch >= 'a') && (ch <= 'z'))
                {
                  t->contents.buf.array[i] = ((char) (( ((unsigned int) (ch))- ((unsigned int) ('a')))+ ((unsigned int) ('A'))));
                }
              i += 1;
            }
          t = t->contents.next;
        }
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   ToLower - returns string, s, after it has had its upper case characters
             replaced by lower case characters.
             The string, s, is not duplicated.
*/

extern "C" DynamicStrings_String DynamicStrings_ToLower (DynamicStrings_String s)
{
  char ch;
  unsigned int i;
  DynamicStrings_String t;

  if (s != NULL)
    {
      MarkInvalid (s);
      t = s;
      while (t != NULL)
        {
          i = 0;
          while (i < t->contents.len)
            {
              ch = t->contents.buf.array[i];
              if ((ch >= 'A') && (ch <= 'Z'))
                {
                  t->contents.buf.array[i] = ((char) (( ((unsigned int) (ch))- ((unsigned int) ('A')))+ ((unsigned int) ('a'))));
                }
              i += 1;
            }
          t = t->contents.next;
        }
    }
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   CopyOut - copies string, s, to a.
*/

extern "C" void DynamicStrings_CopyOut (char *a, unsigned int _a_high, DynamicStrings_String s)
{
  unsigned int i;
  unsigned int l;

  l = Min (_a_high+1, DynamicStrings_Length (s));
  i = 0;
  while (i < l)
    {
      a[i] = DynamicStrings_char (s, static_cast<int> (i));
      i += 1;
    }
  if (i <= _a_high)
    {
      a[i] = ASCII_nul;
    }
}


/*
   char - returns the character, ch, at position, i, in String, s.
*/

extern "C" char DynamicStrings_char (DynamicStrings_String s, int i)
{
  unsigned int c;

  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  if (i < 0)
    {
      c = (unsigned int ) (((int ) (DynamicStrings_Length (s)))+i);
    }
  else
    {
      c = i;
    }
  while ((s != NULL) && (c >= s->contents.len))
    {
      c -= s->contents.len;
      s = s->contents.next;
    }
  if ((s == NULL) || (c >= s->contents.len))
    {
      return ASCII_nul;
    }
  else
    {
      return s->contents.buf.array[c];
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   string - returns the C style char * of String, s.
*/

extern "C" void * DynamicStrings_string (DynamicStrings_String s)
{
  typedef char *string__T2;

  DynamicStrings_String a;
  unsigned int l;
  unsigned int i;
  string__T2 p;

  if (PoisonOn)
    {
      s = CheckPoisoned (s);
    }
  if (s == NULL)
    {
      return NULL;
    }
  else
    {
      if (! s->head->charStarValid)
        {
          l = DynamicStrings_Length (s);
          if (! (s->head->charStarUsed && (s->head->charStarSize > l)))
            {
              DeallocateCharStar (s);
              Storage_ALLOCATE (&s->head->charStar, l+1);
              s->head->charStarSize = l+1;
              s->head->charStarUsed = TRUE;
            }
          p = static_cast<string__T2> (s->head->charStar);
          a = s;
          while (a != NULL)
            {
              i = 0;
              while (i < a->contents.len)
                {
                  (*p) = a->contents.buf.array[i];
                  i += 1;
                  p += 1;
                }
              a = a->contents.next;
            }
          (*p) = ASCII_nul;
          s->head->charStarValid = TRUE;
        }
      return s->head->charStar;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   InitStringDB - the debug version of InitString.
*/

extern "C" DynamicStrings_String DynamicStrings_InitStringDB (const char *a_, unsigned int _a_high, const char *file_, unsigned int _file_high, unsigned int line)
{
  char a[_a_high+1];
  char file[_file_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);
  memcpy (file, file_, _file_high+1);

  return AssignDebug (DynamicStrings_InitString ((const char *) a, _a_high), (const char *) file, _file_high, line, (const char *) "InitString", 10);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   InitStringCharStarDB - the debug version of InitStringCharStar.
*/

extern "C" DynamicStrings_String DynamicStrings_InitStringCharStarDB (void * a, const char *file_, unsigned int _file_high, unsigned int line)
{
  char file[_file_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (file, file_, _file_high+1);

  return AssignDebug (DynamicStrings_InitStringCharStar (a), (const char *) file, _file_high, line, (const char *) "InitStringCharStar", 18);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   InitStringCharDB - the debug version of InitStringChar.
*/

extern "C" DynamicStrings_String DynamicStrings_InitStringCharDB (char ch, const char *file_, unsigned int _file_high, unsigned int line)
{
  char file[_file_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (file, file_, _file_high+1);

  return AssignDebug (DynamicStrings_InitStringChar (ch), (const char *) file, _file_high, line, (const char *) "InitStringChar", 14);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   MultDB - the debug version of MultDB.
*/

extern "C" DynamicStrings_String DynamicStrings_MultDB (DynamicStrings_String s, unsigned int n, const char *file_, unsigned int _file_high, unsigned int line)
{
  char file[_file_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (file, file_, _file_high+1);

  return AssignDebug (DynamicStrings_Mult (s, n), (const char *) file, _file_high, line, (const char *) "Mult", 4);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   DupDB - the debug version of Dup.
*/

extern "C" DynamicStrings_String DynamicStrings_DupDB (DynamicStrings_String s, const char *file_, unsigned int _file_high, unsigned int line)
{
  char file[_file_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (file, file_, _file_high+1);

  return AssignDebug (DynamicStrings_Dup (s), (const char *) file, _file_high, line, (const char *) "Dup", 3);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   SliceDB - debug version of Slice.
*/

extern "C" DynamicStrings_String DynamicStrings_SliceDB (DynamicStrings_String s, int low, int high, const char *file_, unsigned int _file_high, unsigned int line)
{
  char file[_file_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (file, file_, _file_high+1);

  DSdbEnter ();
  s = AssignDebug (DynamicStrings_Slice (s, low, high), (const char *) file, _file_high, line, (const char *) "Slice", 5);
  DSdbExit (s);
  return s;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   PushAllocation - pushes the current allocation/deallocation lists.
*/

extern "C" void DynamicStrings_PushAllocation (void)
{
  DynamicStrings_frame f;

  if (CheckOn)
    {
      Init ();
      Storage_ALLOCATE ((void **) &f, sizeof (DynamicStrings_frameRec));
      f->next = frameHead;
      f->alloc = NULL;
      f->dealloc = NULL;
      frameHead = f;
    }
}


/*
   PopAllocation - test to see that all strings are deallocated since
                   the last push.  Then it pops to the previous
                   allocation/deallocation lists.

                   If halt is true then the application terminates
                   with an exit code of 1.
*/

extern "C" void DynamicStrings_PopAllocation (unsigned int halt)
{
  if (CheckOn)
    {
      if ((DynamicStrings_PopAllocationExemption (halt, NULL)) == NULL)
        {}  /* empty.  */
    }
}


/*
   PopAllocationExemption - test to see that all strings are deallocated, except
                            string, e, since the last push.
                            Then it pops to the previous allocation/deallocation
                            lists.

                            If halt is true then the application terminates
                            with an exit code of 1.
*/

extern "C" DynamicStrings_String DynamicStrings_PopAllocationExemption (unsigned int halt, DynamicStrings_String e)
{
  DynamicStrings_String s;
  DynamicStrings_frame f;
  unsigned int b;

  Init ();
  if (CheckOn)
    {
      /* avoid gcc warning by using compound statement even if not strictly necessary.  */
      if (frameHead == NULL)
        {
          stop ();
          /* writeString ("mismatched number of PopAllocation's compared to PushAllocation's")  */
          M2RTS_Halt ((const char *) "../../gcc-read-write/gcc/m2/gm2-libs/DynamicStrings.mod", 55, 176, (const char *) "PopAllocationExemption", 22, (const char *) "mismatched number of PopAllocation's compared to PushAllocation's", 65);
        }
      else
        {
          if (frameHead->alloc != NULL)
            {
              b = FALSE;
              s = frameHead->alloc;
              while (s != NULL)
                {
                  if (! (((e == s) || (IsOnGarbage (e, s))) || (IsOnGarbage (s, e))))
                    {
                      if (! b)
                        {
                          writeString ((const char *) "the following strings have been lost", 36);
                          writeLn ();
                          b = TRUE;
                        }
                      DumpStringInfo (s, 0);
                    }
                  s = s->debug.next;
                }
              if (b && halt)
                {
                  libc_exit (1);
                }
            }
          frameHead = frameHead->next;
        }
    }
  return e;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}

extern "C" void _M2_DynamicStrings_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
  Initialized = FALSE;
  Init ();
}

extern "C" void _M2_DynamicStrings_fini (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
}
